#include <iostream>
#include <string>
using namespace std;

/**
 * @brief 实现
 *
 */
class Device {
public:
    Device() {
    }
    virtual ~Device(){};

    bool is_enabled() {
        return _is_enabled;
    }
    int get_volume() {
        return _volume_percent;
    }
    virtual void enable()            = 0;
    virtual void disable()           = 0;
    virtual void set_volume(int vol) = 0;

protected:
    bool _is_enabled;
    int  _volume_percent;
};

class TV : public Device {
public:
    ~TV() {
    }
    void enable() override {
        cout << "TV: enable" << endl;
    }
    void disable() override {
        cout << "TV: disable" << endl;
    }

    void set_volume(int vol) {
        cout << "TV: set volume " << vol << endl;
        _volume_percent = vol;
    }
};
class Radio : public Device {
public:
    ~Radio() {
    }
    void enable() override {
        cout << "Radio: enable" << endl;
    }
    void disable() override {
        cout << "Radio: disable" << endl;
    }
    void set_volume(int vol) {
        cout << "Radio: set volume " << vol << endl;
        _volume_percent = vol;
    }
};

/**
 * @brief 抽象/接口
 *
 */
// class Remote {
// public:
//     Remote(Device *dev) :
//         _device(dev) {
//     }
//     virtual void toggle_power() = 0;
//     virtual void volume_down()  = 0;
//     virtual void volume_up()    = 0;

// protected:
//     Device *_device;
// };

class BaseRemote {
public:
    BaseRemote(Device *dev) :
        _device(dev) {
    }
    virtual ~BaseRemote() {
    }

    virtual void toggle_power() {
        if (_device->is_enabled()) {
            _device->disable();
        } else {
            _device->enable();
        }
    }
    virtual void volume_down() {
        _device->set_volume(_device->get_volume() - 1);
    }
    virtual void volume_up() {
        _device->set_volume(_device->get_volume() + 1);
    }

protected:
    Device *_device;
};

class AdvancedRemote : public BaseRemote {
public:
    AdvancedRemote(Device *dev) :
        BaseRemote(dev) {
    }
    void mute() {
        _device->set_volume(0);
    }
};

void client() {
    Device     *device = new TV();
    BaseRemote *remote = new BaseRemote(device);
    remote->toggle_power();
    delete device;
    delete remote;

    device                     = new Radio();
    AdvancedRemote *adv_remote = new AdvancedRemote(device);
    adv_remote->toggle_power();
    adv_remote->volume_up();
    adv_remote->volume_up();
    adv_remote->volume_up();
    adv_remote->mute();
}

/**
 * @brief
 *
 * @param argc
 * @param argv
 * @return int
 */
int main(int argc, char *argv[]) {
    client();
    return 0;
}